home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ghostscript / src / gxclread.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  13KB  |  435 lines

  1. /* Copyright (C) 1991, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* gxclread.c */
  20. /* Command list reading for Ghostscript. */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gpcheck.h"
  24. #include "gserrors.h"
  25. #include "gxdevice.h"
  26. #include "gxdevmem.h"            /* must precede gxclist.h */
  27. #include "gxcldev.h"
  28.  
  29. /* Imported from gxclist.c */
  30. int clist_flush_buffer(P1(gx_device_clist *));
  31.  
  32. /* Print a bitmap for tracing */
  33. #ifdef DEBUG
  34. private void
  35. cmd_print_bits(const byte *data, int height, int raster)
  36. {    int i, j;
  37.     for ( i = 0; i < height; i++ )
  38.        {    const byte *row = data + i * raster;
  39.         dprintf("[L]");
  40.         for ( j = 0; j < raster; j++ )
  41.           dprintf1(" %02x", row[j]);
  42.         dputc('\n');
  43.        }
  44. }
  45. #else
  46. #  define cmd_print_bits(data, height, raster)
  47. #endif
  48.  
  49. /* ------ Reading/rendering ------ */
  50.  
  51. private int clist_render_init(P1(gx_device_clist *));
  52. private int clist_render(P3(gx_device_clist *, gx_device *, int));
  53.  
  54. /* Copy a scan line to the client.  This is where rendering gets done. */
  55. int
  56. clist_get_bits(gx_device *dev, int y, byte *str, byte **actual_data)
  57. {    gx_device_memory *mdev = &cdev->mdev;
  58.     /* Initialize for rendering if we haven't done so yet. */
  59.     if ( cdev->ymin < 0 )
  60.     {    int code = clist_render_init(cdev);
  61.         if ( code < 0 ) return code;
  62.     }
  63.     /* Render a band if necessary, and copy it incrementally. */
  64.     if ( !(y >= cdev->ymin && y < cdev->ymax) )
  65.        {    int band = y / mdev->height;
  66.         int code;
  67.         rewind(cdev->bfile);
  68.         (*mdev->procs->open_device)((gx_device *)mdev);    /* reinitialize */
  69.         code = clist_render(cdev, (gx_device *)mdev, band);
  70.         if ( code < 0 ) return code;
  71.         cdev->ymin = band * mdev->height;
  72.         cdev->ymax = cdev->ymin + mdev->height;
  73.        }
  74.     return (*mdev->procs->get_bits)((gx_device *)mdev,
  75.                     y - cdev->ymin, str, actual_data);
  76. }
  77.  
  78. #undef cdev
  79.  
  80. /* Initialize for reading. */
  81. private int
  82. clist_render_init(gx_device_clist *cdev)
  83. {    gx_device *target = cdev->target;
  84.     byte *base = cdev->mdev.base;    /* save */
  85.     int depth = target->color_info.depth;
  86.     uint raster = gx_device_raster(target, 1);
  87.     const gx_device_memory *mdev = gdev_mem_device_for_bits(depth);
  88.     int code;
  89.     if ( mdev == 0 )
  90.         return_error(gs_error_rangecheck);
  91.     code = clist_flush_buffer(cdev);        /* flush buffer */
  92.     if ( code < 0 ) return 0;
  93.     /* Write the terminating entry in the block file. */
  94.     /* Note that because of copypage, there may be many such entries. */
  95.        {    cmd_block cb;
  96.         cb.band = -1;
  97.         cb.pos = ftell(cdev->cfile);
  98.         clist_write(cdev->bfile, (byte *)&cb, sizeof(cb));
  99.         cdev->bfile_end_pos = ftell(cdev->bfile);
  100.        }
  101.     cdev->mdev = *mdev;
  102.     cdev->mdev.base = base;        /* restore */
  103.     (*target->procs->get_initial_matrix)(target, &cdev->mdev.initial_matrix);
  104.     cdev->mdev.width = target->width;
  105.     cdev->mdev.height = cdev->band_height;
  106.     cdev->mdev.raster = raster;
  107.     cdev->mdev.target = target;
  108.     cdev->ymin = cdev->ymax = 0;
  109. #ifdef DEBUG
  110. if ( gs_debug['l'] | gs_debug['L'] )
  111.     {    extern void cmd_print_stats(P0());
  112.         cmd_print_stats();
  113.     }
  114. #endif
  115.     return 0;
  116. }
  117.  
  118. /* Render one band to a specified target device. */
  119. typedef byte _ss *cb_ptr;
  120. #define cmd_getw(var, p)\
  121. { int _shift = 0; for ( var = 0; var += (int)(*p & 0x7f) << _shift,\
  122.     *p++ > 0x7f; _shift += 7 ) ;\
  123. }
  124. private cb_ptr cmd_read_rect(P2(gx_cmd_rect *, cb_ptr));
  125. private void clist_read(P3(FILE *, byte *, uint));
  126. private cb_ptr clist_read_short_bits(P6(FILE *, byte *, int, int, cb_ptr, cb_ptr));
  127. private int
  128. clist_render(gx_device_clist *cdev, gx_device *tdev, int band)
  129. {    byte cbuf[cbuf_size];
  130.     long bits[255];  /* for short copy_mono bits, must be aligned */
  131.     register cb_ptr cbp;
  132.     cb_ptr cb_limit;
  133.     cb_ptr cb_end;
  134.     FILE *file = cdev->cfile;
  135.     FILE *bfile = cdev->bfile;
  136.     int y0 = band * cdev->band_height;
  137.     gx_clist_state state;
  138.     gx_bitmap state_tile;
  139.     uint tile_bits_size;        /* size of bits of each tile */
  140.     gs_int_point tile_phase;
  141.     cmd_block b_this;
  142.     long pos;
  143.     uint left;
  144. #define cmd_read(ptr, vsize, cbp)\
  145.   if ( cb_end - cbp >= vsize )\
  146.     memcpy(ptr, cbp, vsize), cbp += vsize;\
  147.   else\
  148.    { uint cleft = cb_end - cbp;\
  149.      memcpy(ptr, cbp, cleft); vsize -= cleft;\
  150.      clist_read(file, ptr + cleft, vsize);\
  151.      cbp = cb_end;\
  152.    }
  153. #define cmd_read_short_bits(ptr, bw, ht, cbp)\
  154.   cbp = clist_read_short_bits(file, ptr, bw, ht, cbp, cb_end)
  155.     state = cls_initial;
  156.     state_tile.id = 0;
  157.     tile_phase.x = tile_phase.y = 0;
  158. trd:    clist_read(bfile, (byte *)&b_this, sizeof(b_this));
  159. top:    /* Find the next run of commands for this band. */
  160.     if ( b_this.band < 0 && ftell(bfile) == cdev->bfile_end_pos )
  161.         return 0;    /* end of bfile */
  162.     if ( b_this.band != band ) goto trd;
  163.     pos = b_this.pos;
  164.     clist_read(bfile, (byte *)&b_this, sizeof(b_this));
  165.     fseek(file, pos, SEEK_SET);
  166.     left = (uint)(b_this.pos - pos);
  167.     cb_limit = cbuf + (cbuf_size - cmd_largest_size);
  168.     cb_end = cbuf + cbuf_size;
  169.     cbp = cb_end;
  170.     for ( ; ; )
  171.        {    int op;
  172.         uint bytes;
  173.         int data_x, raster;
  174.         int code;
  175.         cb_ptr source;
  176.         gx_color_index _ss *pcolor;
  177.         /* Make sure the buffer contains a full command. */
  178.         if ( cbp > cb_limit )
  179.            {    uint nread;
  180.             memcpy(cbuf, cbp, cb_end - cbp);
  181.             cbp = cbuf + (cb_end - cbp);
  182.             nread = cb_end - cbp;
  183.             if ( nread > left ) nread = left;
  184.             clist_read(file, cbp, nread);
  185.             cb_end = cbp + nread;
  186.             cbp = cbuf;
  187.             left -= nread;
  188.             if ( cb_limit > cb_end ) cb_limit = cb_end;
  189.            }
  190.         op = *cbp++;
  191.         if_debug2('L', "[L]%s %d:\n",
  192.               cmd_op_names[op >> 4], op & 0xf);
  193.         switch ( op >> 4 )
  194.            {
  195.         case cmd_op_misc >> 4:
  196.             switch ( op )
  197.                {
  198.             case cmd_opv_end_run:
  199.                 goto top;
  200.             case cmd_opv_set_tile_size:
  201.                 cmd_getw(state_tile.size.x, cbp);
  202.                 cmd_getw(state_tile.size.y, cbp);
  203.                 state_tile.raster = ((state_tile.size.x + 31) >> 5) << 2;
  204.                 /* We can't actually know the rep_size, */
  205.                 /* so we play it safe. */
  206.                 state_tile.rep_width = state_tile.size.x;
  207.                 state_tile.rep_height = state_tile.size.y;
  208.                 cdev->tile_slot_size = tile_bits_size =
  209.                     state_tile.raster * state_tile.size.y;
  210.                 break;
  211.             case cmd_opv_set_tile_phase:
  212.                 cmd_getw(state.tile_phase.x, cbp);
  213.                 cmd_getw(state.tile_phase.y, cbp);
  214.                 break;
  215.             default:
  216.                 goto bad_op;
  217.                }
  218.             tile_phase.x = state.tile_phase.x % state_tile.size.x;
  219.             tile_phase.y = (state.tile_phase.y + y0) % state_tile.size.y;
  220.             continue;
  221.         case cmd_op_set_color0 >> 4:
  222.             pcolor = &state.color0;
  223.             goto set_color;
  224.         case cmd_op_set_color1 >> 4:
  225.             pcolor = &state.color1;
  226. set_color:        if ( op & 0xf )
  227.                 *pcolor = (gx_color_index)(long)((op & 0xf) - 2);
  228.             else
  229.             {    memcpy(pcolor, cbp, sizeof(gx_color_index));
  230.                 cbp += sizeof(gx_color_index);
  231.             }
  232.             continue;
  233.         case cmd_op_set_tile_index >> 4:
  234.             state_tile.data = (byte *)tile_slot_ptr(cdev, *cbp);
  235.             cbp++;
  236.             continue;
  237.         case cmd_op_copy_mono >> 4:
  238.             if ( op & 0xf )
  239.                {    cmd_getw(state.rect.x, cbp);
  240.                 cmd_getw(state.rect.y, cbp);
  241.                 state.rect.width = *cbp++;
  242.                 state.rect.height = *cbp++;
  243.                 break;
  244.                }
  245.             /* falls through */
  246.         case cmd_op_fill_rect >> 4:
  247.         case cmd_op_tile_rect >> 4:
  248.         case cmd_op_copy_color >> 4:
  249.             cbp = cmd_read_rect(&state.rect, cbp);
  250.             break;
  251.         case cmd_op_fill_rect_short >> 4:
  252.         case cmd_op_tile_rect_short >> 4:
  253.             state.rect.x += *cbp + cmd_min_short;
  254.             state.rect.width += cbp[1] + cmd_min_short;
  255.             if ( op & 0xf )
  256.                {    state.rect.height += (op & 0xf) + cmd_min_tiny;
  257.                 cbp += 2;
  258.                }
  259.             else
  260.                {    state.rect.y += cbp[2] + cmd_min_short;
  261.                 state.rect.height += cbp[3] + cmd_min_short;
  262.                 cbp += 4;
  263.                }
  264.             break;
  265.         case cmd_op_fill_rect_tiny >> 4:
  266.         case cmd_op_tile_rect_tiny >> 4:
  267.            {    int txy = *cbp++;
  268.             state.rect.x += (txy >> 4) + cmd_min_tiny;
  269.             state.rect.y += (txy & 0xf) + cmd_min_tiny;
  270.             state.rect.width += (op & 0xf) + cmd_min_tiny;
  271.            }    break;
  272.         case cmd_op_set_tile_bits >> 4:
  273.             state_tile.data = (byte *)tile_slot_ptr(cdev, *cbp);
  274.             cbp++;
  275.             if ( state_tile.size.x <= 16 )
  276.                {    cmd_read_short_bits(state_tile.data, 2, state_tile.size.y, cbp);
  277.                }
  278.             else
  279.                {    bytes = tile_bits_size;
  280.                 cmd_read(state_tile.data, bytes, cbp);
  281.                }
  282. #ifdef DEBUG
  283. if ( gs_debug['L'] )
  284.             cmd_print_bits(state_tile.data, state_tile.size.y,
  285.                        state_tile.raster);
  286. #endif
  287.             continue;
  288.         case cmd_op_delta_tile_bits >> 4:
  289.            {    byte *new_data = (byte *)tile_slot_ptr(cdev, *cbp);
  290.             cbp++;
  291.             memcpy(new_data, state_tile.data, tile_bits_size);
  292.             state_tile.data = new_data;
  293.             do
  294.                {    uint offset = *cbp;
  295.                 if ( offset < 0x80 )
  296.                     new_data[offset] ^= cbp[1],
  297.                     cbp += 2;
  298.                 else
  299.                     offset -= 0x80,
  300.                     new_data[offset] ^= cbp[1],
  301.                     new_data[offset + 1] ^= cbp[2],
  302.                     cbp += 3;
  303.                }
  304.             while ( op-- & 0xf );
  305.            }    continue;
  306.         default:
  307. bad_op:            lprintf5("Bad op %02x band %d file pos %ld buf pos %d/%d\n",
  308.                  op, band, ftell(file), (int)(cbp - cbuf), (int)(cb_end - cbuf));
  309.                {    cb_ptr pp;
  310.                 for ( pp = cbuf; pp < cb_end; pp += 10 )
  311.                   lprintf10(" %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  312.                        pp[0], pp[1], pp[2], pp[3], pp[4],
  313.                        pp[5], pp[6], pp[7], pp[8], pp[9]);
  314.                }
  315.             return_error(gs_error_Fatal);
  316.            }
  317.         if_debug4('L', "[L]  x=%d y=%d w=%d h=%d\n",
  318.               state.rect.x, state.rect.y, state.rect.width,
  319.               state.rect.height);
  320.         switch ( op >> 4 )
  321.            {
  322.         case cmd_op_fill_rect >> 4:
  323.         case cmd_op_fill_rect_short >> 4:
  324.         case cmd_op_fill_rect_tiny >> 4:
  325.             code = (*tdev->procs->fill_rectangle)
  326.               (tdev, state.rect.x, state.rect.y - y0,
  327.                state.rect.width, state.rect.height, state.color1);
  328.             break;
  329.         case cmd_op_tile_rect >> 4:
  330.         case cmd_op_tile_rect_short >> 4:
  331.         case cmd_op_tile_rect_tiny >> 4:
  332.             code = (*tdev->procs->tile_rectangle)
  333.               (tdev, &state_tile,
  334.                state.rect.x, state.rect.y - y0,
  335.                state.rect.width, state.rect.height,
  336.                state.color0, state.color1,
  337.                tile_phase.x, tile_phase.y);
  338.             break;
  339.         case cmd_op_copy_mono >> 4:
  340.             if ( op & 0xf )
  341.                {    data_x = (op & 0xf) - 1;
  342.                 raster = 4;
  343.                 cmd_read_short_bits((byte *)bits, (data_x + state.rect.width + 7) >> 3, state.rect.height, cbp);
  344.                 source = (byte *)bits;
  345.                 goto copy;
  346.                }
  347.             /* falls through */
  348.         case cmd_op_copy_color >> 4:
  349.             cmd_getw(data_x, cbp);
  350.             cmd_getw(raster, cbp);
  351.             bytes = state.rect.height * raster;
  352.             /* copy_mono and copy_color have ensured that */
  353.             /* the bits will fit in a single buffer. */
  354. #ifdef DEBUG
  355.             if ( bytes > cbuf_size )
  356.             {    lprintf2("bitmap size exceeds buffer!  raster=%d height=%d\n",
  357.                     raster, state.rect.height);
  358.                 return gs_error_ioerror;
  359.             }
  360. #endif
  361.             cmd_read(cbuf, bytes, cbp);
  362.             source = cbuf;
  363. copy:
  364. #ifdef DEBUG
  365. if ( gs_debug['L'] )
  366.    {            dprintf2("[L]  data_x=%d raster=%d\n",
  367.                  data_x, raster);
  368.             cmd_print_bits(source, state.rect.height, raster);
  369.    }
  370. #endif
  371.             code = (op >> 4 == (byte)cmd_op_copy_mono >> 4 ?
  372.               (*tdev->procs->copy_mono)
  373.                 (tdev, source, data_x, raster, gx_no_bitmap_id,
  374.                  state.rect.x, state.rect.y - y0,
  375.                  state.rect.width, state.rect.height,
  376.                  state.color0, state.color1) :
  377.               (*tdev->procs->copy_color)
  378.                 (tdev, source, data_x, raster, gx_no_bitmap_id,
  379.                  state.rect.x, state.rect.y - y0,
  380.                  state.rect.width, state.rect.height));
  381.             break;
  382.            }
  383.         if ( code < 0 ) return_error(code);
  384.        }
  385. }
  386.  
  387. /* The typical implementations of fread and fseek */
  388. /* are extremely inefficient for small counts, */
  389. /* so we use loops instead. */
  390. private void
  391. clist_read(FILE *f, byte *str, uint len)
  392. {    switch ( len )
  393.        {
  394.     default: fread(str, 1, len, f); break;
  395.     case 8: *str++ = (byte)getc(f);
  396.     case 7: *str++ = (byte)getc(f);
  397.     case 6: *str++ = (byte)getc(f);
  398.     case 5: *str++ = (byte)getc(f);
  399.     case 4: *str++ = (byte)getc(f);
  400.     case 3: *str++ = (byte)getc(f);
  401.     case 2: *str++ = (byte)getc(f);
  402.     case 1: *str = (byte)getc(f);
  403.        }
  404. }
  405.  
  406. /* Read a short bitmap */
  407. private cb_ptr
  408. clist_read_short_bits(FILE *file, byte *data, register int bwidth, int height,
  409.   cb_ptr cbp, cb_ptr cb_end)
  410. {    uint bytes = bwidth * height;
  411.     byte *pdata = data + bytes;
  412.     byte *udata = data + (height << log2_align_bitmap_mod);
  413.     cmd_read(data, bytes, cbp);
  414.     while ( --height > 0 )        /* first row is in place already */
  415.        {    udata -= align_bitmap_mod, pdata -= bwidth;
  416.         switch ( bwidth )
  417.            {
  418.         case 3: udata[2] = pdata[2];
  419.         case 2: udata[1] = pdata[1];
  420.         case 1: udata[0] = pdata[0];
  421.            }
  422.        }
  423.     return cbp;
  424. }
  425.  
  426. /* Read a rectangle. */
  427. private cb_ptr
  428. cmd_read_rect(register gx_cmd_rect *prect, register cb_ptr cbp)
  429. {    cmd_getw(prect->x, cbp);
  430.     cmd_getw(prect->y, cbp);
  431.     cmd_getw(prect->width, cbp);
  432.     cmd_getw(prect->height, cbp);
  433.     return cbp;
  434. }
  435.